# Create your views here.
import datetime
import json
import string
from django.contrib.auth.decorators import login_required
from django.http import HttpResponse
from django.shortcuts import render_to_response, redirect, get_object_or_404
from django.template.context import RequestContext
from opengoal.forms import GoalForm, JournalForm, SubGoalForm, TaskForm
from opengoal.models import Goal, EntityTag, Tag, Journal, Task

class TabPages:
    tabs = {'dashboard': '', 'goals': '', 'tasks': '', 'calendar': '', 'journal': '', 'reports': ''}

    def __activate(self, active_tab):
        for tab in self.tabs:
            if active_tab == tab:
                self.tabs[tab] = 'active'
            else:
                self.tabs[tab] = ''

    def activate_dashboard(self):
        self.__activate('dashboard')

    def activate_goals(self):
        self.__activate('goals')

    def activate_tasks(self):
        self.__activate('tasks')

    def activate_calendar(self):
        self.__activate('calendar')

    def activate_journal(self):
        self.__activate('journal')

    def activate_reports(self):
        self.__activate('reports')

tab_pages = TabPages()

def current_tab(request):
    return {'tabs': tab_pages.tabs}


@login_required
def add_goal_sub(request, parent_id):
    parent = get_object_or_404(Goal, pk=parent_id)
    form = SubGoalForm(initial={
        'due_date': parent.due_date,
        #'parent_goal' : goal.start_date,
        'show_on_dashboard': parent.show_on_dashboard,
        'parent':parent.pk
        })
    return _edit_goal(request, form, parent=parent)


@login_required
def edit_goal(request, goal_id):
    goal = get_object_or_404(Goal, pk=goal_id)
    parent = goal.parent if goal.parent else None
    if  request.method == 'POST':
        form = GoalForm(request.POST, instance=goal, initial={'goal':goal.pk})
    else:
        form = GoalForm(instance=goal, initial={'goal':goal.pk}) if not goal.parent else SubGoalForm(instance=goal, initial={'parent': parent.pk, 'goal':goal.pk})
    return _edit_goal(request, form, goal, parent=parent)


@login_required
def add_goal_copy(request, goal_id):
    goal = get_object_or_404(Goal, pk=goal_id)
    form = GoalForm(instance=goal)
    return _edit_goal(request, form)


@login_required
def add_goal(request):
    if request.method != 'POST':
        form = GoalForm(initial={'start_date':datetime.today()})
    elif 'parent' in request.POST and request.POST['parent']: # Subgoal
        if 'goal' in request.POST and request.POST['goal']: # EDIT Subgoal
            goal = Goal.objects.get(pk=request.POST['goal'])
            form = SubGoalForm(request.POST, instance=goal)
        else: # ADD SubGoal
            form = SubGoalForm(request.POST)
    elif 'goal' in request.POST and request.POST['goal']: # EDIT normal goal
        goal = Goal.objects.get(pk=request.POST['goal'])
        form = GoalForm(request.POST, instance=goal)
    else: # New Goal
        form = GoalForm(request.POST)
    return _edit_goal(request, form)


def _edit_goal(request, form, goal=None, *args, **kwargs):
    tab_pages.activate_goals()
    user = request.user
    if request.method == 'POST':
        if form.is_valid():
            goal = form.save(commit=False)
            goal.user = user
            if 'parent' in request.POST:
                parent_id = request.POST['parent']
                goal.parent = get_object_or_404(Goal, pk=parent_id)
            goal.save()
            if 'categories' in form.cleaned_data:
                categories = form.cleaned_data['categories']
                categories = split_tags(categories)
                save_new_tags(categories, Tag.categories(user), Tag.category, user)
                delete_tags(goal, 'CATEGORY')
                save_tags(goal, categories, 'CATEGORY', user)
            return redirect('/goals/')

    categories = [tag.name for tag in Tag.categories(user)]
    goals = Goal.objects.filter(parent__isnull=True)
    template_name = 'opengoal/add_goal.html' if type(form) is GoalForm else 'opengoal/add_sub_goal.html'
    params = {'goals':goals, 'form': form, 'categories': categories, 'goal': goal}
    params = dict(params, **kwargs)
    return render_to_response(template_name, params,
        context_instance=RequestContext(request))


def split_tags(tags):
    tags = list(set([tag.strip(' \t\n\r') for tag in string.split(tags, ',')]))
    return tags

def delete_tags(entity, type):
    EntityTag.objects.filter(tag__type=type, entity_id=entity.pk).delete()

def save_new_tags(new_tags, persisted_tags, tag_callback, user):
    persisteds = [tag.name for tag in persisted_tags]
    for tag_name in new_tags:
        if tag_name not in persisteds:
            tag_callback(tag_name, user).save()


def save_tags(entity, tags, type, user):
    for tag_name in tags:
        tag = Tag.objects.get(user=user, name=tag_name, type=type)
        if len(EntityTag.objects.filter(entity_id=entity.pk, tag=tag)): # goal has already this tag
            continue
        EntityTag(entity_id=entity.pk, tag=tag).save()


@login_required
def goal_list(request):
    tab_pages.activate_goals()
    if request.method == 'POST': # Edit goal
        goal = Goal.objects.get(pk=request.POST['goal'])
        _edit_goal(request, GoalForm(request.POST, instance=goal))
        return HttpResponse(json.dumps(goal.as_json));
    goals = request.user.goal_set.filter(parent_id__isnull=True)
    forms = [GoalForm(instance=goal) for goal in goals]
    datas = zip(goals, forms)
    return render_to_response('opengoal/goals.html', {'datas': datas,}, context_instance=RequestContext(request))


@login_required
def journals(request):
    tab_pages.activate_journal()
    user = request.user
    goals = user.goal_set.all()
    journals = user.journal_set
    filter_goal_id = -1
    if 'goal' in request.GET and request.GET['goal']:
        filter_goal_id = request.GET['goal']
        journals = journals.filter(goal_id=filter_goal_id)
    else:
        journals = user.journal_set.all()
    return render_to_response('opengoal/journals.html', {'goals':goals, 'journals':journals, 'filter_goal_id': int(filter_goal_id)},
        context_instance=RequestContext(request))

@login_required
def journal_edit(request, journal_id):
    journal = None
    if journal_id:
        journal = get_object_or_404(Journal, pk=journal_id)
    return __journal_edit(request, journal)


def __journal_edit(request, journal):
    tab_pages.activate_journal()
    user = request.user
    if request.method == 'POST':
        form = JournalForm(request.POST, instance=journal)
        if form.is_valid():
            journal = form.save(commit=False)
            journal.user = user
            journal.save()

            tags = form.cleaned_data['tags']
            tags = split_tags(tags)
            save_new_tags(tags, Tag.journal_tags(user), Tag.journal_tag, user)
            delete_tags(journal, 'JOURNAL')
            save_tags(journal, tags, 'JOURNAL', user)
            return redirect('/journals/')
    tags_str = ''
    if journal:
        tags_str = journal.tags
    form = JournalForm(instance=journal, initial={'tags':tags_str})
    goals = user.goal_set.all()
    tags = [tag.name for tag in Tag.journal_tags(user)]
    filter_goal_id = journal.goal_id if journal else None
    return render_to_response('opengoal/journal_edit.html', {'form': form,
                                                             'goals': goals,
                                                             'tags':tags,
                                                             'journal':journal,
                                                             'filter_goal_id': filter_goal_id},
        context_instance=RequestContext(request))

@login_required
def delete_goal(request, goal_id):
    goal = get_object_or_404(Goal, pk=goal_id)
    goal.delete()
    return redirect('/goals/')

@login_required
def delete_journal(request, journal_id):
    journal = get_object_or_404(Journal, pk=journal_id)
    journal.delete()
    return redirect('/journals/')


@login_required
def tasks(request, goal_id):
    if request.method == 'GET' and 'goal' in request.GET:
        return redirect('/tasks%s/' % request.GET['goal'])
    tab_pages.activate_tasks()

    user = request.user
    error = None
    if request.method == 'POST':
        if 'task' in request.POST and request.POST['task']:
            task_id = request.POST['task']
            task = get_object_or_404(Task, pk=task_id)
            form = TaskForm(request.POST, instance=task)
        else:
            form = TaskForm(request.POST)
        if form.is_valid():
            task = form.save(commit=False)
            task.user = user
            task.spent_time = '0:00'
            if not task.estimated_time:
                task.estimated_time = datetime.time(0, 0)
            if 'goal' in form.cleaned_data and form.cleaned_data['goal']:
                task.goal = Goal.objects.get(pk=form.cleaned_data['goal'])
            task.save()

            tags = form.cleaned_data['tags']
            if tags:
                tags = split_tags(tags)
                save_new_tags(tags, Tag.task_tag(user), Tag.task_tag, user)
                delete_tags(task, 'TASK_TAG')
                save_tags(task, tags, 'TASK_TAG', user)
            filter_goal_id = task.goal.pk if task.goal else ''
            return redirect('/tasks%s/' % filter_goal_id)
        else:
            error = 'Please correct the error: %s!' % form.errors


    goal = get_object_or_404(Goal, pk=goal_id) if goal_id else None
    active_tasks_q = goal.task_set if goal else user.task_set
    active_tasks_q = active_tasks_q.filter(completed_date__isnull=True).all()
    completed_tasks_q = goal.completed_task_set.all() if goal else user.task_set.filter(completed_date__isnull=False).all()

    completed_tasks = add_form_to_task(completed_tasks_q)
    active_tasks = add_form_to_task(active_tasks_q)

    goals = user.goal_set.all()
    new_form = TaskForm(initial={'goal':goal.pk}, auto_id='new_%s_') if goal else TaskForm(auto_id='new_%s_')
    return render_to_response('opengoal/tasks.html', {'error': error,
                                                      'goals':goals,
                                                      'goal':goal,
                                                      'active_tasks': active_tasks,
                                                      'completed_tasks': completed_tasks,
                                                      'new_form':new_form},
        context_instance=RequestContext(request)
    )

def add_form_to_task(query):
    list = []
    for task in query:
        goal_pk = task.goal.pk if task.goal else None
        task.form = TaskForm(instance=task, auto_id=('task%s_%%s_'%task.pk), initial={'goal':goal_pk, 'task':task.pk})
        list.append(task)
    return list

def delete_task(request, task_id):
    task = get_object_or_404(Task, pk=task_id)
    task.delete()
    return redirect('/tasks%s/' % (task.goal.pk if task.goal else ''))


def complete_task(request, task_id):
    if request.method == 'POST':
        task = get_object_or_404(Task, pk=task_id)
        task.completed_date = datetime.datetime.today() if not task.completed_date else None
        task.save()
        return redirect('/tasks%s/' % (task.goal.pk if task.goal else ''))